package org.hospital.entity;
// default package

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;

import static org.hibernate.criterion.Example.create;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.annotation.Transactional;

/**
 	* A data access object (DAO) providing persistence and search support for Project entities.
 			* Transaction control of the save(), update() and delete() operations 
		can directly support Spring container-managed transactions or they can be augmented	to handle user-managed Spring transactions. 
		Each of these methods provides additional information for how to configure it for the desired type of transaction control. 	
	 * @see .Project
  * @author MyEclipse Persistence Tools 
 */
    @Transactional   
public class ProjectDAO  {
	     private static final Logger log = LoggerFactory.getLogger(ProjectDAO.class);
		//property constants
	public static final String CREATOR_ID = "creatorId";
	public static final String CATEGORY = "category";
	public static final String NAME = "name";
	public static final String UNIT_PRICE = "unitPrice";
	public static final String DOCTOR_COST = "doctorCost";
	public static final String CLINIC_COST = "clinicCost";
	public static final String EXCUTOR_COST = "excutorCost";
	public static final String TYPE = "type";
	public static final String STATUS = "status";



    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory){
       this.sessionFactory = sessionFactory;
    }

    private Session getCurrentSession(){
     return sessionFactory.getCurrentSession(); 
    }
	protected void initDao() {
		//do nothing
	}
	
	
	
	/**
	 * 获取门诊[startTime,endTime]所有有效费用项目(收入和支出)
	 * @param clinicId
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public List<Project> getClinicFundProject(int clinicId,long startTime,long endTime) {
		log.debug("getClinicFundProject instance");
        try {
        	StringBuilder hql = new StringBuilder();
        	hql.append("SELECT DISTINCT pj ");
        	hql.append("FROM Project as pj,Bill as b,BillProject as bp ");
        	hql.append("WHERE b.billId = bp.id.billId ");
        	hql.append("AND pj.projectId = bp.id.projectId ");
        	hql.append("AND pj.category = 'fundProject' ");
        	hql.append("AND b.status = 0 ");
        	hql.append("AND b.category = 'fundBill' ");
        	hql.append("AND b.clinicId = :clinicId ");
        	hql.append("AND b.datetime >= :startTime ");
        	hql.append("AND b.datetime < :endTime ");
        	Query q = getCurrentSession().createQuery(hql.toString());
        	q.setParameter("clinicId", clinicId);
        	q.setParameter("startTime", new Date(startTime));
        	q.setParameter("endTime", new Date(endTime));
        	List<Project> result = q.list();
            log.debug("getClinicFundProject successful");
            return result;
        } catch (RuntimeException re) {
            log.error("getClinicFundProject failed", re);
            throw re;
        }
		
	}
	
	
	/**
	 * 获取客户拥有的治疗项目
	 * @param clientId
	 * @return
	 */
	public List<Project> getClientProject(int clientId) {
		log.debug("getClientProject instance");
        try {
        	String hql = "SELECT DISTINCT pj "
        			+ "FROM Project as pj,MedicalCard as mc "
        			+ "WHERE mc.projectId = pj.projectId "
        			+ "AND mc.status = 0 "
        			+ "AND mc.clientId = :clientId";
        	Query q = getCurrentSession().createQuery(hql);
        	q.setParameter("clientId", clientId);
        	List<Project> result = q.list();
            log.debug("getClientProject successful");
            return result;
        } catch (RuntimeException re) {
            log.error("getClientProject failed", re);
            throw re;
        }
	}
	
	/**
	 * 获取门诊在[startTime,endTime]内开过的治疗项目Id
	 * 门诊执行者在[startTime,endTime]内执行过治疗项目Id
	 * @param clinicId
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public List<Project> getClinicTreatmentProject(Integer clinicId, Long startTime, Long endTime) {
		
		log.debug("getClinicTreatmentProject Bill instance");
		try {
			StringBuilder sql = new StringBuilder();
			sql.append("SELECT DISTINCT pj.* ");
			sql.append("FROM BillProject as bp,Bill as b,Project as pj ");
			sql.append("WHERE bp.billId = b.billId ");
			sql.append("AND bp.projectId = pj.projectId ");//查看单据中的治疗项目
			sql.append("AND b.category = 'treatmentBill' "); //治疗单据
			sql.append("AND b.status = 0 "); //有效单据
			sql.append("AND b.clinicId = :clinicId "); //属于该门诊
			sql.append("AND b.datetime >= :startTime ");
			sql.append("AND b.datetime < :endTime ");
			sql.append("UNION ");
			sql.append("SELECT DISTINCT pj.* ");//查看治疗信息中的治疗项目
			sql.append("FROM Project as pj,TreatInfo as ti,MedicalCard as mc ");
			sql.append("WHERE  mc.projectId = pj.projectId ");
			sql.append("AND ti.medicalCardId = mc.medicalCardId ");
			sql.append("AND ti.clinicId = :clinicId "); //属于该门诊
			sql.append("AND ti.treatTime >= :startTime ");
			sql.append("AND ti.treatTime < :endTime "); 
			
			SQLQuery q = getCurrentSession().createSQLQuery(sql.toString());
			q.addEntity(Project.class);
			q.setParameter("clinicId", clinicId);
			q.setParameter("startTime", new Date(startTime));
			q.setParameter("endTime", new Date(endTime));
			
			List<Project> result = q.list();
			log.debug("getClinicTreatmentProject success");
			return result;
		} catch (RuntimeException re) {
			log.error("getClinicTreatmentProject failed", re);
			throw re;
		}
	}
	
	/**
	 * 获取科室在[startTime,endTime]内开过的治疗项目Id
	 * @param departmentId
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public List getDepartmentTreatmentProject(Integer departmentId, Long startTime, Long endTime) {
		log.debug("getClinicTreatmentProject Bill instance");
		try {
			StringBuilder sql = new StringBuilder();
			sql.append("SELECT DISTINCT pj.* ");
			sql.append("FROM BillProject as bp,Bill as b,Project as pj ");
			sql.append("WHERE bp.billId = b.billId ");
			sql.append("AND bp.projectId = pj.projectId ");//查看单据中的治疗项目
			sql.append("AND b.category = 'treatmentBill' "); //治疗单据
			sql.append("AND b.status = 0 "); //有效单据
			sql.append("AND b.departmentId = :departmentId "); //属于该科室
			sql.append("AND b.datetime >= :startTime ");
			sql.append("AND b.datetime < :endTime ");
			sql.append("UNION ");
			sql.append("SELECT DISTINCT pj.* ");//查看治疗信息中的治疗项目
			sql.append("FROM Project as pj,TreatInfo as ti,MedicalCard as mc ");
			sql.append("WHERE  mc.projectId = pj.projectId ");
			sql.append("AND ti.medicalCardId = mc.medicalCardId ");
			sql.append("AND ti.departmentId = :departmentId "); //属于该科室的
			sql.append("AND ti.treatTime >= :startTime "); 
			sql.append("AND ti.treatTime < :endTime "); 
			
			SQLQuery q = getCurrentSession().createSQLQuery(sql.toString());
			q.addEntity(Project.class);
			q.setParameter("departmentId", departmentId);
			q.setParameter("startTime", new Date(startTime));
			q.setParameter("endTime", new Date(endTime));
			
			List result = q.list();
			return result;
		} catch (RuntimeException re) {
			log.error("getClinicTreatmentProject failed", re);
			throw re;
		}
	}
    
	public List<Project> getByProperties(Map properties) {
		Criteria c = getCurrentSession().createCriteria(Project.class);
		c.add(Restrictions.allEq(properties));
		c.list();
		return c.list();
	}
	
    public void save(Project transientInstance) {
        log.debug("saving Project instance");
        try {
            getCurrentSession().save(transientInstance);
            log.debug("save successful");
        } catch (RuntimeException re) {
            log.error("save failed", re);
            throw re;
        }
    }
    
	public void delete(Project persistentInstance) {
        log.debug("deleting Project instance");
        try {
            getCurrentSession().delete(persistentInstance);
            log.debug("delete successful");
        } catch (RuntimeException re) {
            log.error("delete failed", re);
            throw re;
        }
    }
    
    public Project findById( java.lang.Integer id) {
        log.debug("getting Project instance with id: " + id);
        try {
            Project instance = (Project) getCurrentSession()
                    .get("org.hospital.entity.Project", id);
            return instance;
        } catch (RuntimeException re) {
            log.error("get failed", re);
            throw re;
        }
    }
    
    
    public List<Project> findByExample(Project instance) {
        log.debug("finding Project instance by example");
        try {
            List<Project> results = (List<Project>) getCurrentSession() .createCriteria("Project").add( create(instance) ).list();
            log.debug("find by example successful, result size: " + results.size());
            return results;
        } catch (RuntimeException re) {
            log.error("find by example failed", re);
            throw re;
        }
    }    
    
    public List findByProperty(String propertyName, Object value) {
      log.debug("finding Project instance with property: " + propertyName
            + ", value: " + value);
      try {
         String queryString = "from Project as model where model." 
         						+ propertyName + "= ?";
         Query queryObject = getCurrentSession().createQuery(queryString);
		 queryObject.setParameter(0, value);
		 return queryObject.list();
      } catch (RuntimeException re) {
         log.error("find by property name failed", re);
         throw re;
      }
	}

	public List<Project> findByCreatorId(Object creatorId
	) {
		return findByProperty(CREATOR_ID, creatorId
		);
	}
	
	public List<Project> findByCategory(Object category
	) {
		return findByProperty(CATEGORY, category
		);
	}
	
	public List<Project> findByName(Object name
	) {
		return findByProperty(NAME, name
		);
	}
	
	public List<Project> findByUnitPrice(Object unitPrice
	) {
		return findByProperty(UNIT_PRICE, unitPrice
		);
	}
	
	public List<Project> findByDoctorCost(Object doctorCost
	) {
		return findByProperty(DOCTOR_COST, doctorCost
		);
	}
	
	public List<Project> findByClinicCost(Object clinicCost
	) {
		return findByProperty(CLINIC_COST, clinicCost
		);
	}
	
	public List<Project> findByExcutorCost(Object excutorCost
	) {
		return findByProperty(EXCUTOR_COST, excutorCost
		);
	}
	
	public List<Project> findByType(Object type
	) {
		return findByProperty(TYPE, type
		);
	}
	
	public List<Project> findByStatus(Object status
	) {
		return findByProperty(STATUS, status
		);
	}
	

	public List findAll() {
		log.debug("finding all Project instances");
		try {
			String queryString = "from Project";
	         Query queryObject = getCurrentSession().createQuery(queryString);
			 return queryObject.list();
		} catch (RuntimeException re) {
			log.error("find all failed", re);
			throw re;
		}
	}
	
    public Project merge(Project detachedInstance) {
        log.debug("merging Project instance");
        try {
            Project result = (Project) getCurrentSession()
                    .merge(detachedInstance);
            log.debug("merge successful");
            return result;
        } catch (RuntimeException re) {
            log.error("merge failed", re);
            throw re;
        }
    }

    public void attachDirty(Project instance) {
        log.debug("attaching dirty Project instance");
        try {
            getCurrentSession().saveOrUpdate(instance);
            log.debug("attach successful");
        } catch (RuntimeException re) {
            log.error("attach failed", re);
            throw re;
        }
    }
    
    public void attachClean(Project instance) {
        log.debug("attaching clean Project instance");
        try {
                      	getCurrentSession().buildLockRequest(LockOptions.NONE).lock(instance);
          	            log.debug("attach successful");
        } catch (RuntimeException re) {
            log.error("attach failed", re);
            throw re;
        }
    }

	public static ProjectDAO getFromApplicationContext(ApplicationContext ctx) {
    	return (ProjectDAO) ctx.getBean("ProjectDAO");
	}
}